package com.objecteffects.template.web.action;

import javax.servlet.http.Cookie;

import com.google.inject.Inject;

import com.objecteffects.template.model.UserEntity;
import com.objecteffects.template.service.UserEntityService;
import com.objecteffects.template.util.logger.InjectLogger;
import com.objecteffects.template.web.utils.PasswordTypeConverter;
import com.objecteffects.template.web.utils.TemplateCookie;

import org.slf4j.Logger;

import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.DontValidate;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.validation.SimpleError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;

/**
 * @author Rusty Wright
 */
public class UserLoginActionBean extends BaseActionBean {
    @InjectLogger
    private Logger log;

    private final UserEntityService userEntityService;
    private final TemplateCookie templateCookie;

    @Validate(required = true)
    private String username;

    @Validate(required = true, converter = PasswordTypeConverter.class)
    private String password;

    private Boolean rememberMe = Boolean.FALSE;

    private UserEntity userEntity;

    @Inject
    UserLoginActionBean(final UserEntityService _userEntityService,
        final TemplateCookie _templateCookie) {
        this.userEntityService = _userEntityService;
        this.templateCookie = _templateCookie;
    }

    @SuppressWarnings("static-method")
    @DontValidate
    @DefaultHandler
    public Resolution startHandler() throws Exception {
        return new ForwardResolution(TemplateView.LOGIN);
    }

    public Resolution login() {
        this.getContext().setUserId(this.userEntity.getId());

        this.log.debug("rememberMe: {}", this.rememberMe);

        if (this.rememberMe != null && this.rememberMe.booleanValue()) {
            this.saveCookie();
        }

        return new RedirectResolution(TumblrStartUrlActionBean.class);
    }

    @DontValidate
    public Resolution cancel() {
        this.log.debug("cancel");

        return new RedirectResolution(this.getClass());
    }

    /**
     * Make a new cookie and persist it.
     */
    private void saveCookie() {
        final Cookie cookie;

        cookie = this.templateCookie.makeCookie();

        this.userEntity.setHash(cookie.getValue());

        this.userEntityService.update(this.userEntity);

        /* 30 days */
        cookie.setMaxAge(30 * 24 * 60 * 60);

        this.getContext().getResponse().addCookie(cookie);
    }

    /**
     * @return the username
     */
    public String getUsername() {
        return this.username;
    }

    /**
     * @param username
     *        the username to set
     */
    public void setUsername(final String _username) {
        this.username = _username;
    }

    /**
     * @return the password
     */
    public String getPassword() {
        return this.password;
    }

    /**
     * @param password
     *        the password to set
     */
    public void setPassword(final String _password) {
        this.password = _password;
    }

    public Boolean getRememberMe() {
        return this.rememberMe;
    }

    public void setRememberMe(final Boolean _rememberMe) {
        this.rememberMe = _rememberMe;
    }

    @ValidationMethod
    public void validateUsernameAndPasswords(final ValidationErrors errors) {
        final UserEntity formUserEntity =
            this.userEntityService.findByUserName(this.username);

        if (formUserEntity == null) {
            errors.add("username", new SimpleError(this.username +
                " is not a registered user."));

            return;
        }

        if (!formUserEntity.getPassword().equals(this.password)) {
            errors.add("password", new SimpleError("Incorrect password."));

            return;
        }

        this.userEntity = formUserEntity;
    }
}
